package manongfanshen.t1_wait_t2;

import com.google.common.base.Stopwatch;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.ThreadUtil;

import java.util.concurrent.TimeUnit;

import static util.ThreadUtil.sleepForMilliSeconds;

/**
 * @author ChangLiang
 * @date 2020/3/18
 */
public class MainV2Test {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    @DisplayName("Main wait for ThreadA and ThreadB complete")
    public void test() {

        Thread thread = new Thread() {
            @Override
            public void run() {
                ThreadUtil.sleepForMilliSeconds(3_000);
                logger.info("thread complete");
                // this: thread-1
                synchronized (this) {
                    this.notify();
                }
            }
        };

        Stopwatch stopwatch = Stopwatch.createStarted();
        thread.start();
        // ensure threadA start
        sleepForMilliSeconds(200);
        // mock main do something
        sleepForMilliSeconds(1_000);
        synchronized (thread) {
            try {
                // 一个线程一旦调用了某个对象的wait方法，其就进入到这个对象关联的monitor的waitSet中
                // 而且会释放刚刚获取的锁

                // 即便被唤醒了，这个线程也不能立即执行，因为唤醒后，这个线程还要重新获取这个对象的锁，
                // 其需要被唤醒并抢到锁之后才会进入到就绪Runnable状态，等待操作系统调度

                // main thread进入waiting状态 进入thread关联的monitor waitset中等待唤醒
                thread.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        logger.info("main thread finish, elapsed time {} milliseconds",stopwatch.elapsed(TimeUnit.MILLISECONDS));
    }


}
